﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.model.Instance;
using l1cs.server.model;
using l1cs.server.datatables;
using l1cs.server.serverpackets;
using l1cs.server.templates;

namespace l1cs.server.clientpackets
{
    public class C_Result : ClientBasePacket
    {
        private static Logger _log = Logger.getLogger( typeof( C_Result ).FullName );
        private const String _C_RESULT = "[C] C_Result";

        public C_Result( byte[] abyte0, ClientThread clientthread )
            : base( abyte0 )
        {
            int npcObjectId = readD();
            int resultType = readC();
            int size = readC();
            int unknown = readC();

            L1PcInstance pc = clientthread.getActiveChar();
            int level = pc.getLevel();

            int npcId = 0;
            String npcImpl = "";
            bool isPrivateShop = false;
            bool tradable = true;
            L1Object findObject = L1World.getInstance().findObject( npcObjectId );
            if ( findObject != null )
            {
                int diffLocX = Math.Abs( pc.getX() - findObject.getX() );
                int diffLocY = Math.Abs( pc.getY() - findObject.getY() );
                // 3マス以上離れた場合アクション無効
                if ( diffLocX > 3 || diffLocY > 3 )
                {
                    return;
                }
                if ( findObject is L1NpcInstance )
                {
                    L1NpcInstance targetNpc = (L1NpcInstance)findObject;
                    npcId = targetNpc.getNpcTemplate().get_npcId();
                    npcImpl = targetNpc.getNpcTemplate().getImpl();
                }
                else if ( findObject is L1PcInstance )
                {
                    isPrivateShop = true;
                }
            }

            if ( resultType == 0 && size != 0
                    && string.Compare (npcImpl, "L1Merchant", true ) == 0 )
            { // アイテム購入
                L1Shop shop = ShopTable.getInstance().get( npcId );
                L1ShopBuyOrderList orderList = new L1ShopBuyOrderList( shop );//shop.newBuyOrderList();
                for ( int i = 0; i < size; i++ )
                {
                    orderList.add( readD(), readD() );
                }
                shop.sellItems( pc, orderList );
            }
            else if ( resultType == 1 && size != 0
                  && string.Compare (npcImpl, "L1Merchant",true ) == 0 )
            { // アイテム売却
                L1Shop shop = ShopTable.getInstance().get( npcId );
                L1ShopSellOrderList orderList = new L1ShopSellOrderList( shop, pc );//shop.newSellOrderList(pc);
                for ( int i = 0; i < size; i++ )
                {
                    orderList.add( readD(), readD() );
                }
                shop.buyItems( orderList );
            }
            else if ( resultType == 2 && size != 0
                  && string.Compare (npcImpl, "L1Dwarf",true ) == 0&& level >= 5 )
            { // 自分の倉庫に格納
                int objectId, count;
                for ( int i = 0; i < size; i++ )
                {
                    tradable = true;
                    objectId = readD();
                    count = readD();
                    L1Object l1object = pc.getInventory().getItem( objectId );
                    L1ItemInstance item = (L1ItemInstance)l1object;
                    if ( !item.getItem().isTradable() )
                    {
                        tradable = false;
                        pc.sendPackets( new S_ServerMessage( 210, item.getItem()
                                .getName() ) ); // \f1%0は捨てたりまたは他人に讓ることができません。
                    }
                    //Object[] petlist = pc.getPetList().values().toArray();
                    foreach ( Object petObject in pc.getPetList().Values )
                    {
                        if ( petObject is L1PetInstance )
                        {
                            L1PetInstance pet = (L1PetInstance)petObject;
                            if ( item.getId() == pet.getItemObjId() )
                            {
                                tradable = false;
                                // \f1%0は捨てたりまたは他人に讓ることができません。
                                pc.sendPackets( new S_ServerMessage( 210, item
                                        .getItem().getName() ) );
                                break;
                            }
                        }
                    }
                    //Object[] dolllist = pc.getDollList().values().toArray();
                    foreach ( Object dollObject in pc.getDollList().Values )
                    {
                        if ( dollObject is L1DollInstance )
                        {
                            L1DollInstance doll = (L1DollInstance)dollObject;
                            if ( item.getId() == doll.getItemObjId() )
                            {
                                tradable = false;
                                pc.sendPackets( new S_ServerMessage( 1181 ) ); // 該当のマジックドールは現在使用中です。
                                break;
                            }
                        }
                    }
                    if ( pc.getDwarfInventory().checkAddItemToWarehouse( item, count,
                            L1Inventory.WAREHOUSE_TYPE_PERSONAL ) == L1Inventory
                                    .SIZE_OVER )
                    {
                        pc.sendPackets( new S_ServerMessage( 75 ) ); // \f1これ以上ものを置く場所がありません。
                        break;
                    }
                    if ( tradable )
                    {
                        pc.getInventory().tradeItem( objectId, count,
                                pc.getDwarfInventory() );
                        pc.turnOnOffLight();
                    }
                }
            }
            else if ( resultType == 3 && size != 0
                  && string.Compare (npcImpl, "L1Dwarf",true )==0 && level >= 5 )
            { // 自分の倉庫から取り出し
                int objectId, count;
                L1ItemInstance item;
                for ( int i = 0; i < size; i++ )
                {
                    objectId = readD();
                    count = readD();
                    item = pc.getDwarfInventory().getItem( objectId );
                    if ( pc.getInventory().checkAddItem( item, count ) == L1Inventory.OK ) // 容量重量確認及びメッセージ送信
                    {
                        if ( pc.getInventory().consumeItem( L1ItemId.ADENA, 30 ) )
                        {
                            pc.getDwarfInventory().tradeItem( item, count,
                                    pc.getInventory() );
                        }
                        else
                        {
                            pc.sendPackets( new S_ServerMessage( 189 ) ); // \f1アデナが不足しています。
                            break;
                        }
                    }
                    else
                    {
                        pc.sendPackets( new S_ServerMessage( 270 ) ); // \f1持っているものが重くて取引できません。
                        break;
                    }
                }
            }
            else if ( resultType == 4 && size != 0
                  && string.Compare (npcImpl, "L1Dwarf" ,true)==0 && level >= 5 )
            { // クラン倉庫に格納
                int objectId, count;
                if ( pc.getClanid() != 0 )
                { // クラン所属
                    for ( int i = 0; i < size; i++ )
                    {
                        tradable = true;
                        objectId = readD();
                        count = readD();
                        L1Clan clan = L1World.getInstance().getClan(
                                pc.getClanname() );
                        L1Object l1object = pc.getInventory().getItem( objectId );
                        L1ItemInstance item = (L1ItemInstance)l1object;
                        if ( clan != null )
                        {
                            if ( !item.getItem().isTradable() )
                            {
                                tradable = false;
                                pc.sendPackets( new S_ServerMessage( 210, item
                                        .getItem().getName() ) ); // \f1%0は捨てたりまたは他人に讓ることができません。
                            }
                            if ( item.getBless() >= 128 )
                            { // 封印された装備
                                tradable = false;
                                pc.sendPackets( new S_ServerMessage( 210, item
                                        .getItem().getName() ) ); // \f1%0は捨てたりまたは他人に讓ることができません。
                            }
                            //Object[] petlist = pc.getPetList().values().toArray();
                            foreach ( Object petObject in pc.getPetList().Values )
                            {
                                if ( petObject is L1PetInstance )
                                {
                                    L1PetInstance pet = (L1PetInstance)petObject;
                                    if ( item.getId() == pet.getItemObjId() )
                                    {
                                        tradable = false;
                                        // \f1%0は捨てたりまたは他人に讓ることができません。
                                        pc.sendPackets( new S_ServerMessage( 210,
                                                item.getItem().getName() ) );
                                        break;
                                    }
                                }
                            }
                            //Object[] dolllist = pc.getDollList().values().toArray();
                            foreach ( Object dollObject in pc.getDollList().Values )
                            {
                                if ( dollObject is L1DollInstance )
                                {
                                    L1DollInstance doll = (L1DollInstance)dollObject;
                                    if ( item.getId() == doll.getItemObjId() )
                                    {
                                        tradable = false;
                                        pc.sendPackets( new S_ServerMessage( 1181 ) ); // 該当のマジックドールは現在使用中です。
                                        break;
                                    }
                                }
                            }
                            if ( clan.getDwarfForClanInventory()
                                    .checkAddItemToWarehouse( item, count,
                                            L1Inventory.WAREHOUSE_TYPE_CLAN )
                                                    == L1Inventory.SIZE_OVER )
                            {
                                pc.sendPackets( new S_ServerMessage( 75 ) ); // \f1これ以上ものを置く場所がありません。
                                break;
                            }
                            if ( tradable )
                            {
                                pc.getInventory().tradeItem( objectId, count,
                                        clan.getDwarfForClanInventory() );
                                pc.turnOnOffLight();
                            }
                        }
                    }
                }
                else
                {
                    pc.sendPackets( new S_ServerMessage( 208 ) ); // \f1血盟倉庫を使用するには血盟に加入していなくてはなりません。
                }
            }
            else if ( resultType == 5 && size != 0
                  &&string.Compare ( npcImpl, "L1Dwarf",true )==0 && level >= 5 )
            { // クラン倉庫から取り出し
                int objectId, count;
                L1ItemInstance item;

                L1Clan clan = L1World.getInstance().getClan( pc.getClanname() );
                if ( clan != null )
                {
                    for ( int i = 0; i < size; i++ )
                    {
                        objectId = readD();
                        count = readD();
                        item = clan.getDwarfForClanInventory().getItem( objectId );
                        if ( pc.getInventory().checkAddItem( item, count ) == L1Inventory.OK )
                        { // 容量重量確認及びメッセージ送信
                            if ( pc.getInventory().consumeItem( L1ItemId.ADENA, 30 ) )
                            {
                                clan.getDwarfForClanInventory().tradeItem( item,
                                        count, pc.getInventory() );
                            }
                            else
                            {
                                pc.sendPackets( new S_ServerMessage( 189 ) ); // \f1アデナが不足しています。
                                break;
                            }
                        }
                        else
                        {
                            pc.sendPackets( new S_ServerMessage( 270 ) ); // \f1持っているものが重くて取引できません。
                            break;
                        }
                    }
                    clan.setWarehouseUsingChar( 0 ); // クラン倉庫のロックを解除
                }
            }
            else if ( resultType == 5 && size == 0
                  && string.Compare (npcImpl, "L1Dwarf" ,true)==0 )
            { // クラン倉庫から取り出し中にCancel、または、ESCキー
                L1Clan clan = L1World.getInstance().getClan( pc.getClanname() );
                if ( clan != null )
                {
                    clan.setWarehouseUsingChar( 0 ); // クラン倉庫のロックを解除
                }
            }
            else if ( resultType == 8 && size != 0
                  &&string.Compare ( npcImpl, "L1Dwarf",true )==0 && level >= 5 && pc
                          .isElf() )
            { // 自分のエルフ倉庫に格納
                int objectId, count;
                for ( int i = 0; i < size; i++ )
                {
                    tradable = true;
                    objectId = readD();
                    count = readD();
                    L1Object l1object = pc.getInventory().getItem( objectId );
                    L1ItemInstance item = (L1ItemInstance)l1object;
                    if ( !item.getItem().isTradable() )
                    {
                        tradable = false;
                        pc.sendPackets( new S_ServerMessage( 210, item.getItem()
                                .getName() ) ); // \f1%0は捨てたりまたは他人に讓ることができません。
                    }
                    //Object[] petlist = pc.getPetList().values().toArray();
                    foreach ( Object petObject in pc.getPetList().Values )
                    {
                        if ( petObject is L1PetInstance )
                        {
                            L1PetInstance pet = (L1PetInstance)petObject;
                            if ( item.getId() == pet.getItemObjId() )
                            {
                                tradable = false;
                                // \f1%0は捨てたりまたは他人に讓ることができません。
                                pc.sendPackets( new S_ServerMessage( 210, item
                                        .getItem().getName() ) );
                                break;
                            }
                        }
                    }
                    //Object[] dolllist = pc.getDollList().values().toArray();
                    foreach ( Object dollObject in pc.getDollList().Values )
                    {
                        if ( dollObject is L1DollInstance )
                        {
                            L1DollInstance doll = (L1DollInstance)dollObject;
                            if ( item.getId() == doll.getItemObjId() )
                            {
                                tradable = false;
                                pc.sendPackets( new S_ServerMessage( 1181 ) ); // 該当のマジックドールは現在使用中です。
                                break;
                            }
                        }
                    }
                    if ( pc.getDwarfForElfInventory().checkAddItemToWarehouse( item,
                            count, L1Inventory.WAREHOUSE_TYPE_PERSONAL ) ==
                                    L1Inventory.SIZE_OVER )
                    {
                        pc.sendPackets( new S_ServerMessage( 75 ) ); // \f1これ以上ものを置く場所がありません。
                        break;
                    }
                    if ( tradable )
                    {
                        pc.getInventory().tradeItem( objectId, count,
                                pc.getDwarfForElfInventory() );
                        pc.turnOnOffLight();
                    }
                }
            }
            else if ( resultType == 9 && size != 0
                  && string.Compare( npcImpl, "L1Dwarf",true )==0 && level >= 5 && pc
                          .isElf() )
            { // 自分のエルフ倉庫から取り出し
                int objectId, count;
                L1ItemInstance item;
                for ( int i = 0; i < size; i++ )
                {
                    objectId = readD();
                    count = readD();
                    item = pc.getDwarfForElfInventory().getItem( objectId );
                    if ( pc.getInventory().checkAddItem( item, count ) == L1Inventory
                            .OK )
                    { // 容量重量確認及びメッセージ送信
                        if ( pc.getInventory().consumeItem( 40494, 2 ) )
                        { // ミスリル
                            pc.getDwarfForElfInventory().tradeItem( item, count,
                                    pc.getInventory() );
                        }
                        else
                        {
                            pc.sendPackets( new S_ServerMessage( 337, "$767" ) ); // \f1%0が不足しています。
                            break;
                        }
                    }
                    else
                    {
                        pc.sendPackets( new S_ServerMessage( 270 ) ); // \f1持っているものが重くて取引できません。
                        break;
                    }
                }
            }
            else if ( resultType == 0 && size != 0 && isPrivateShop )
            { // 個人商店からアイテム購入
                int order;
                int count;
                int price;
                List<L1PrivateShopSellList> sellList;
                L1PrivateShopSellList pssl;
                int itemObjectId;
                int sellPrice;
                int sellTotalCount;
                int sellCount;
                L1ItemInstance item;
                bool[] isRemoveFromList = new bool[8];

                L1PcInstance targetPc = null;
                if ( findObject is L1PcInstance )
                {
                    targetPc = (L1PcInstance)findObject;
                    if ( targetPc == null )
                    {
                        return;
                    }
                }
                if ( targetPc.isTradingInPrivateShop() )
                {
                    return;
                }
                sellList = targetPc.getSellList();
                lock ( sellList )
                {
                    // 売り切れが発生し、閲覧中のアイテム数とリスト数が異なる
                    if ( pc.getPartnersPrivateShopItemCount() != sellList.Count )
                    {
                        return;
                    }
                    targetPc.setTradingInPrivateShop( true );

                    for ( int i = 0; i < size; i++ )
                    { // 購入予定の商品
                        order = readD();
                        count = readD();
                        pssl = (L1PrivateShopSellList)sellList[order];
                        itemObjectId = pssl.getItemObjectId();
                        sellPrice = pssl.getSellPrice();
                        sellTotalCount = pssl.getSellTotalCount(); // 売る予定の個数
                        sellCount = pssl.getSellCount(); // 売った累計
                        item = targetPc.getInventory().getItem( itemObjectId );
                        if ( item == null )
                        {
                            continue;
                        }
                        if ( count > sellTotalCount - sellCount )
                        {
                            count = sellTotalCount - sellCount;
                        }
                        if ( count == 0 )
                        {
                            continue;
                        }

                        if ( pc.getInventory().checkAddItem( item, count ) == L1Inventory.OK )
                        { // 容量重量確認及びメッセージ送信
                            for ( int j = 0; j < count; j++ )
                            { // オーバーフローをチェック
                                if ( sellPrice * j > 2000000000 )
                                {
                                    pc.sendPackets( new S_ServerMessage( 904, // 総販売価格は%dアデナを超過できません。
                                            "2000000000" ) );
                                    targetPc.setTradingInPrivateShop( false );
                                    return;
                                }
                            }
                            price = count * sellPrice;
                            if ( pc.getInventory().checkItem( L1ItemId.ADENA, price ) )
                            {
                                L1ItemInstance adena = pc.getInventory()
                                        .findItemId( L1ItemId.ADENA );
                                if ( targetPc != null && adena != null )
                                {
                                    if ( targetPc.getInventory().tradeItem( item,
                                            count, pc.getInventory() ) == null )
                                    {
                                        targetPc.setTradingInPrivateShop( false );
                                        return;
                                    }
                                    pc.getInventory().tradeItem( adena, price,
                                            targetPc.getInventory() );
                                    String message = item.getItem().getName()
                                            + " (" + Convert.ToString( count ) + ")";
                                    targetPc.sendPackets( new S_ServerMessage( 877, // %1%o
                                        // %0に販売しました。
                                            pc.getName(), message ) );
                                    pssl.setSellCount( count + sellCount );
                                    sellList[order] = pssl;
                                    if ( pssl.getSellCount() == pssl
                                            .getSellTotalCount() )
                                    { // 売る予定の個数を売った
                                        isRemoveFromList[order] = true;
                                    }
                                }
                            }
                            else
                            {
                                pc.sendPackets( new S_ServerMessage( 189 ) ); // \f1アデナが不足しています。
                                break;
                            }
                        }
                        else
                        {
                            pc.sendPackets( new S_ServerMessage( 270 ) ); // \f1持っているものが重くて取引できません。
                            break;
                        }
                    }
                    // 売り切れたアイテムをリストの末尾から削除
                    for ( int i = 7; i >= 0; i-- )
                    {
                        if ( isRemoveFromList[i] )
                        {
                            sellList.RemoveAt( i );
                        }
                    }
                    targetPc.setTradingInPrivateShop( false );
                }
            }
            else if ( resultType == 1 && size != 0 && isPrivateShop )
            { // 個人商店にアイテム売却
                int count;
                int order;
                List<L1PrivateShopBuyList> buyList;
                L1PrivateShopBuyList psbl;
                int itemObjectId;
                L1ItemInstance item;
                int buyPrice;
                int buyTotalCount;
                int buyCount;
                //L1ItemInstance targetItem;
                bool[] isRemoveFromList = new bool[8];

                L1PcInstance targetPc = null;
                if ( findObject is L1PcInstance )
                {
                    targetPc = (L1PcInstance)findObject;
                    if ( targetPc == null )
                    {
                        return;
                    }
                }
                if ( targetPc.isTradingInPrivateShop() )
                {
                    return;
                }
                targetPc.setTradingInPrivateShop( true );
                buyList = targetPc.getBuyList();

                for ( int i = 0; i < size; i++ )
                {
                    itemObjectId = readD();
                    count = readCH();
                    order = readC();
                    item = pc.getInventory().getItem( itemObjectId );
                    if ( item == null )
                    {
                        continue;
                    }
                    psbl = (L1PrivateShopBuyList)buyList[order];
                    buyPrice = psbl.getBuyPrice();
                    buyTotalCount = psbl.getBuyTotalCount(); // 買う予定の個数
                    buyCount = psbl.getBuyCount(); // 買った累計
                    if ( count > buyTotalCount - buyCount )
                    {
                        count = buyTotalCount - buyCount;
                    }
                    if ( item.isEquipped() )
                    {
                        pc.sendPackets( new S_ServerMessage( 905 ) ); // 装備しているアイテムは販売できません。
                        continue;
                    }

                    if ( targetPc.getInventory().checkAddItem( item, count ) == L1Inventory.OK )
                    { // 容量重量確認及びメッセージ送信
                        for ( int j = 0; j < count; j++ )
                        { // オーバーフローをチェック
                            if ( buyPrice * j > 2000000000 )
                            {
                                targetPc.sendPackets( new S_ServerMessage( 904, // 総販売価格は%dアデナを超過できません。
                                        "2000000000" ) );
                                return;
                            }
                        }
                        if ( targetPc.getInventory().checkItem( L1ItemId.ADENA,
                                count * buyPrice ) )
                        {
                            L1ItemInstance adena = targetPc.getInventory()
                                    .findItemId( L1ItemId.ADENA );
                            if ( adena != null )
                            {
                                targetPc.getInventory().tradeItem( adena,
                                        count * buyPrice, pc.getInventory() );
                                pc.getInventory().tradeItem( item, count,
                                        targetPc.getInventory() );
                                psbl.setBuyCount( count + buyCount );
                                buyList[order] = psbl;
                                if ( psbl.getBuyCount() == psbl.getBuyTotalCount() )
                                { // 買う予定の個数を買った
                                    isRemoveFromList[order] = true;
                                }
                            }
                        }
                        else
                        {
                            targetPc.sendPackets( new S_ServerMessage( 189 ) ); // \f1アデナが不足しています。
                            break;
                        }
                    }
                    else
                    {
                        pc.sendPackets( new S_ServerMessage( 271 ) ); // \f1相手が物を持ちすぎていて取引できません。
                        break;
                    }
                }
                // 買い切ったアイテムをリストの末尾から削除
                for ( int i = 7; i >= 0; i-- )
                {
                    if ( isRemoveFromList[i] )
                    {
                        buyList.RemoveAt( i );
                    }
                }
                targetPc.setTradingInPrivateShop( false );
            }
        }

        override
        public String getType()
        {
            return _C_RESULT;
        }

    }
}